狂神JUC并发编程笔记

您所在的位置:网站首页 juc 狂神 狂神JUC并发编程笔记

狂神JUC并发编程笔记

2024-07-12 22:34| 来源: 网络整理| 查看: 265

视频来自: https://www.bilibili.com/video/BV1B7411L7tE?p=5&spm_id_from=pageDriver

看到一个新东西不会,狂神会先看源码

JUC = java.util.conrrunent

创建线程的三种方式 extends thread, implement runnable, implement callable接口

常规的实现并发的方式,用synchronized,以及

new Thread(new Runnable() { @Override public void run() { String a = "run 1"; } }).start();

上面代码在java 8以后可用lambda表达式:

new Thread(() -> { String a = "run 1"; } }).start();

锁的实现方式,Lock三部曲

1、 new ReentrantLock();

2. lock.lock(); //加锁

3. try { xxx} catch {} finaly { lock.unlock()}//解锁

池化技术: 事先准备好资源,有人要用,就来我这里拿,用完之后还给我

默认大小: 2 最小值、最大值

线程池的好处:

1. 降低资源消耗

2.提高响应的速度

3.(因为放到池子里了)方便管理

线程复用,控制最大并发数,管理线程

线程池: 三大方法,7种参数,4种拒绝策略

线程池三大方法 public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue())); } public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); } public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue()); } 线程池七大参数 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {

按参数顺序依次对应:

1.核心线程数 线程池里面最小的活跃线程数 2.最大线程数 线程池里面最大的活跃线程数

3.保活时间 线程不工作的最大时间,超时了没有人调用就会释放

4.时间单位 超时用的时间单位 5.工作队列: 用来储存要执行,但是未执行的线程(也即为阻塞的线程)

6.线程工厂 用来创建线程的,一般不用动

7.拒绝策略 

线程池的执行流程,任务来了先放入核心线程池里面,其次放入非核心线程,否则进入工作队列

Volitale 不保证原子性 public class VolatileNotAtomicTest { private volatile static int num = 0; public static void add() { ++num;// ++num和num++都是非原子操作,一行对应3-4行汇编指令 } public static void main(String[] args) { for (int i = 1; i { for(int j= 0; j < 1000; j++) { add(); } }).start(); } while (Thread.activeCount() > 2) { Thread.yield(); } System.out.println(num); // num 一般小于 20000,因为没有原子性 } }

 保证有序性的原理是指令重排序,保证可见性的原理是MESE一致性缓存协议,以及CPU嗅探机制

深入理解CAS

Unsafe类: 因为java无法操作内存,而c++可以,Unsafe是Java的后门,通过这个类,调用native方法,来操作内存

public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); } public final int getAndAddInt(Object this, long valueOffset, int increment) { int previousValue ; do { previousValue = this.getIntVolatile(this, valueOffset); } while(!this.compareAndSwapInt(this, valueOffset, previousValue, previousValue + increment)); // 如果当前对象内存的值(this + valueOffset) 还是和我期望的值 previousValue相等 // 那么将该对象内存值改为 previousValue + increment // compareAndSwapInt 是CPU原语言,操作很快 return var5; }

 上述自旋操作,

池的最大线程数到底该如何定义

CPU 密集型: 几核,就是几, 可以保持CPI的效率最高,如下图,CPU核 = 逻辑处理器数量,即12个

如何获取核数:

System.out.println(Runtime.getRuntime().availableProcessors());

 IO 密集型: 判断你程序中十分耗IO的线程,有多少个,比如有15个任务比较耗费线程,那么就设置最大线程数为两倍,30个

四大函数式接口

标明了@FunctionalInterface的接口

"lambda表达式就是为了优化匿名内部类而生"

Consumer, Function, Predicate, Supplier

只要是函数式接口,就能用lambda表达式简化

BlockingQueue四组API

add, remove element(返回队首)会抛出异常

offer,poll, peek(返回队首) 不会抛出异常

put,take  一直阻塞,string.sout

offer("element", 2, Timeunit.SECOND),poll(2, Timeunit.SECOND)  超时(2S)退出

ArrayBlockingQueue 基于数组结构的队列

LinkedBlockingQueue 基于链表结构的队列



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3